/**
 * 网络请求工具类
 * 基于uni.request封装，支持uniapp多端适配
 */

import { getEnv } from './env.js'

// 基础配置
const config = {
  // 开发环境使用 Vite 代理（相对路径），生产环境使用完整地址
  // baseURL: (typeof window !== 'undefined' && window.location && window.location.hostname === 'localhost' && window.location.port === '5173')
  //   ? '' // 开发环境使用相对路径，通过 Vite 代理转发
  //   : getEnv('VUE_APP_BASE_API', 'http://localhost:6000'), // 生产环境或其他情况使用完整地址
  baseURL: (typeof window !== 'undefined' && window.location && window.location.hostname === 'localhost' && window.location.port === '5173')
    ? '' // 开发环境使用相对路径，通过 Vite 代理转发
    : getEnv('VUE_APP_BASE_API', 'http://8.145.55.161:6000'), // 生产环境或其他情况使用完整地址
  timeout: 40000,
  header: {
    'Content-Type': 'application/json'
  }
}

// 构建完整URL
function buildURL(url, params) {
  if (!params) return url
  
  const query = Object.keys(params)
    .filter(key => params[key] !== undefined && params[key] !== null)
    .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
    .join('&')
  
  return query ? `${url}${url.includes('?') ? '&' : '?'}${query}` : url
}

// 请求方法
function request(options) {
  return new Promise((resolve, reject) => {
    // 合并配置
    const requestConfig = {
      ...config,
      ...options,
      header: {
        ...config.header,
        ...options.header
      }
    }
    
    // 处理环境变量：优先使用传入的 baseURL（H5 开发为相对路径''），否则再取环境值
    const baseURL = (requestConfig.baseURL !== undefined)
      ? requestConfig.baseURL
      : getEnv('VUE_APP_BASE_API', 'http://localhost:6000')
    requestConfig.baseURL = baseURL

    // 请求拦截处理
    const interceptedConfig = requestInterceptor(requestConfig)
    
    // 构建完整URL
    const fullUrl = buildURL(interceptedConfig.url, interceptedConfig.params)

    // uni.request配置
    const uniRequestConfig = {
      url: interceptedConfig.baseURL + fullUrl,
      method: (interceptedConfig.method || 'GET').toUpperCase(),
      header: interceptedConfig.header,
      timeout: interceptedConfig.timeout,
      data: interceptedConfig.data
    }

    // 调试日志
    console.log('发送请求:', {
      url: uniRequestConfig.url,
      method: uniRequestConfig.method,
      header: uniRequestConfig.header,
      data: uniRequestConfig.data
    })
    
    // 发送请求
    // 在H5环境下，如果数据是FormData，使用fetch API
    // #ifdef H5
    if (uniRequestConfig.data instanceof FormData) {
      console.log('使用fetch发送FormData请求')

      // 构建fetch请求头
      const fetchHeaders = { ...uniRequestConfig.header }
      // 不要设置Content-Type，让浏览器自动设置
      delete fetchHeaders['Content-Type']

      fetch(uniRequestConfig.url, {
        method: uniRequestConfig.method,
        headers: fetchHeaders,
        body: uniRequestConfig.data
      })
      .then(response => {
        // 构造类似uni.request的响应格式
        return response.text().then(text => {
          let data
          try {
            data = JSON.parse(text)
          } catch (e) {
            data = text
          }

          const uniResponse = {
            statusCode: response.status,
            data: data,
            header: {}
          }

          // 转换headers
          response.headers.forEach((value, key) => {
            uniResponse.header[key] = value
          })

          responseInterceptor(uniResponse, resolve, reject, requestConfig)
        })
      })
      .catch(error => {
        console.error('Fetch请求失败:', error)
        handleRequestError(error, reject, requestConfig)
      })

      return
    }
    // #endif

    uni.request({
      ...uniRequestConfig,
      success: (response) => {
        responseInterceptor(response, resolve, reject, requestConfig)
      },
      fail: (error) => {
        handleRequestError(error, reject, requestConfig)
      }
    })
  })
}

// 请求拦截器
function requestInterceptor(config) {
  // 显示加载提示 - 默认不显示，遵循用户体验偏好
  if (config.loading === true) {
    if (typeof uni !== 'undefined') {
      uni.showLoading({
        title: config.loadingText || '加载中...',
        mask: true
      })
    }
  }
  
  // 添加token - 优先使用accessToken
  const accessToken = typeof uni !== 'undefined' ? uni.getStorageSync('accessToken') : (typeof localStorage !== 'undefined' ? localStorage.getItem('accessToken') : '')
  if (accessToken) {
    config.header['Authorization'] = `Bearer ${accessToken}`
  }
  
  // 添加目的港信息
  const selectedPort = typeof uni !== 'undefined' ? 
    uni.getStorageSync('selectedPort') : 
    (typeof localStorage !== 'undefined' ? JSON.parse(localStorage.getItem('selectedPort') || '{}') : {})
  
  if (selectedPort && selectedPort.code) {
    config.header['X-Port-Code'] = selectedPort.code
  }
  
  // 添加设备信息
  config.header['X-Client-Type'] = typeof uni !== 'undefined' ? 'uniapp' : 'web'
  
  return config
}

// 响应拦截器
function responseInterceptor(response, resolve, reject, requestConfig) {
  // 隐藏加载提示
  if (typeof uni !== 'undefined') {
    uni.hideLoading()
  }
  
  const { data, statusCode } = response
  
  // HTTP状态码检查
  if (statusCode !== 200) {
    console.error('响应拦截器 - HTTP状态码错误:', statusCode)
    handleHttpError(statusCode, data, reject, requestConfig)
    return
  }
  
  // 对于boolean类型的直接响应
  if (typeof data === 'boolean') {
    resolve(data)
    return
  }
  
  // 对于直接返回的对象数据（如Product实体、数组等）
  if (data && typeof data === 'object') {
    // 检查是否是Product对象（有productId字段）
    if (data.productId && typeof data.productId === 'number') {
      console.log('检测到Product对象响应，直接返回:', data)
      resolve(data)
      return
    }
    
    // 检查是否是数组
    if (Array.isArray(data)) {
      console.log('检测到数组响应，直接返回:', data)
      resolve(data)
      return
    }
    
    // 检查是否是分页对象（有records字段）
    if (data.records && Array.isArray(data.records)) {
      console.log('检测到分页对象响应，直接返回:', data)
      resolve(data)
      return
    }
    
    // 检查是否有id字段的普通对象
    if (data.id && typeof data.id === 'number') {
      console.log('检测到实体对象响应，直接返回:', data)
      resolve(data)
      return
    }
  }
  
  // 业务状态码检查（兼容无业务包装的成功数据）
  const hasBizFlag = data && (
    typeof data.code !== 'undefined' ||
    typeof data.success !== 'undefined' ||
    typeof data.status !== 'undefined'
  )
  
  if (!hasBizFlag) {
    // 没有业务包装，但也不在上面的直接对象范围内，尝试直接返回
    console.log('无业务包装的响应，直接返回数据:', data)
    resolve(data)
    return
  }
  
  // 处理有业务包装的响应
  if (data.code === 0 || data.code === 200 || data.code === 'SUCCESS' || data.success === true || data.status === 'success') {
    resolve(data)
  } else {
    // 业务错误处理
    const errorMsg = data.message || data.msg || data.error || '请求失败'
    console.error('响应拦截器 - 业务错误:', {
      code: data.code,
      message: errorMsg,
      fullResponse: data,
      requestUrl: requestConfig.url
    })

    // 特殊错误码处理
    if (data.code === 401 || data.code === 'UNAUTHORIZED') {
      handleUnauthorized()
      reject(new Error('登录已过期，请重新登录'))
      return
    }

    // 显示错误信息
    if (requestConfig.showError !== false && !requestConfig.silent) {
      showError(errorMsg)
    } else if (requestConfig.silent) {
      console.log('业务错误（静默处理）:', errorMsg)
    }

    reject(new Error(errorMsg))
  }
}

// 处理请求错误
function handleRequestError(error, reject, requestConfig) {
  // 确保隐藏加载提示（无论是否显示了）
  if (typeof uni !== 'undefined') {
    uni.hideLoading()
  }
  
  const errorMsg = error.errMsg || '网络连接失败'
  
  // 显示错误信息
  if (requestConfig.showError !== false && !requestConfig.silent) {
    showError(errorMsg)
  } else if (requestConfig.silent) {
    console.log('网络错误（静默处理）:', errorMsg)
  }
  
  reject(new Error(errorMsg))
}

// 处理HTTP错误
function handleHttpError(status, data, reject, requestConfig) {
  let errorMsg = '网络请求失败'
  
  switch (status) {
    case 400:
      errorMsg = data?.message || '请求参数错误'
      break
    case 401:
      errorMsg = '未授权访问'
      handleUnauthorized()
      break
    case 403:
      errorMsg = '访问被禁止'
      break
    case 404:
      // 临时注释掉404错误提示，避免用户不存在的错误显示
      // errorMsg = '请求地址不存在'
      errorMsg = data?.message || '数据获取失败'
      break
    case 409:
      errorMsg = data?.message || '资源冲突'
      break
    case 500:
      errorMsg = '服务器内部错误'
      break
    case 502:
      errorMsg = '网关错误'
      break
    case 503:
      errorMsg = '服务不可用'
      break
    case 504:
      errorMsg = '网关超时'
      break
    default:
      errorMsg = data?.message || `请求失败(${status})`
  }
  
  // 显示错误信息
  if (requestConfig.showError !== false) {
    showError(errorMsg)
  }
  
  reject(new Error(errorMsg))
}

// 处理未授权
function handleUnauthorized() {
  // 清除本地存储
  if (typeof uni !== 'undefined') {
    uni.removeStorageSync('accessToken')
    uni.removeStorageSync('refreshToken')
    uni.removeStorageSync('userInfo')
    uni.reLaunch({
      url: '/pages/auth/login'
    })
  } else {
    localStorage.removeItem('accessToken')
    localStorage.removeItem('refreshToken')
    localStorage.removeItem('userInfo')
    // Web端跳转登录
    window.location.href = '/login'
  }
}

// 显示错误信息
function showError(message, silent = false) {
  if (silent) {
    // 静默处理，只在控制台输出
    console.log('请求错误（静默处理）:', message)
    return
  }

  if (typeof uni !== 'undefined') {
    uni.showToast({
      title: message,
      icon: 'none',
      duration: 2000
    })
  } else {
    // Web端错误提示
    console.error(message)
    // 这里可以集成其他错误提示组件
  }
}

// 文件上传方法
function uploadFile(url, filePath, options = {}) {
  console.log('开始文件上传:', { url, filePath, options })
  
  return new Promise((resolve, reject) => {
    if (typeof uni === 'undefined') {
      console.error('文件上传仅支持uniapp环境')
      reject(new Error('文件上传仅支持uniapp环境'))
      return
    }
    
    const {
      name = 'file',
      formData = {},
      header = {},
      showProgress = true,
      showErrorMsg = true  // 重命名参数以避免冲突
    } = options
    
    // 添加token - 使用accessToken保持一致性
    const accessToken = uni.getStorageSync('accessToken')
    if (accessToken) {
      header['Authorization'] = `Bearer ${accessToken}`
      console.log('添加授权头:', accessToken.substring(0, 20) + '...')
    } else {
      console.warn('未找到accessToken')
    }
    
    // 显示上传进度
    if (showProgress) {
      uni.showLoading({
        title: '上传中...',
        mask: true
      })
    }
    
    // 构建完整URL - 确保正确处理相对路径
    let uploadUrl
    if (url.startsWith('http')) {
      uploadUrl = url
    } else {
      // 在开发环境中，使用相对路径通过代理
      if (typeof window !== 'undefined' && window.location && window.location.hostname === 'localhost') {
        uploadUrl = url // 使用相对路径，通过Vite代理
      } else {
        uploadUrl = getEnv('VUE_APP_BASE_API', 'http://localhost:6000') + url
      }
    }
    
    console.log('上传URL:', uploadUrl)
    console.log('上传参数:', { filePath, name, formData, header })
    
    uni.uploadFile({
      url: uploadUrl,
      filePath,
      name,
      formData,
      header,
      success: (response) => {
        console.log('上传成功响应:', response)
        console.log('响应状态码:', response.statusCode)
        console.log('响应数据类型:', typeof response.data)
        console.log('响应原始数据:', response.data)
        
        try {
          // 检查HTTP状态码
          if (response.statusCode !== 200) {
            throw new Error(`HTTP错误: ${response.statusCode}`)
          }
          
          // 尝试解析JSON数据
          let data
          if (typeof response.data === 'string') {
            data = JSON.parse(response.data)
          } else {
            data = response.data
          }
          
          console.log('解析后的数据:', data)
          console.log('数据结构 - code:', data.code, 'success:', data.success, 'message:', data.message)
          
          // 判断成功条件 - 适配多种响应格式
          const isSuccess = data.success === true || 
                          data.code === 'SUCCESS' || 
                          data.code === 0 ||
                          data.code === '0' ||
                          (data.code && data.message && data.message.includes('成功')) // 如果有code和成功消息
          
          if (isSuccess) {
            // 对于OCR等需要具体数据的接口，返回完整的response data
            console.log('上传成功，返回数据:', data)
            resolve(data)
          } else {
            const errorMsg = data.message || data.msg || data.error || '上传失败'
            console.error('上传业务错误:', errorMsg)
            if (showErrorMsg) {
              showError(errorMsg)
            }
            reject(new Error(errorMsg))
          }
        } catch (parseError) {
          console.log('解析JSON失败，原始数据:', response.data)
          console.error('JSON解析错误:', parseError)
          
          // 如果响应数据不是JSON格式，但状态码是200，尝试直接返回数据
          if (response.statusCode === 200) {
            console.log('虽然JSON解析失败，但状态码200，尝试直接返回原始数据')
            resolve(response.data)
          } else {
            const errorMsg = `上传失败: HTTP ${response.statusCode}`
            console.error('上传失败，状态码:', response.statusCode)
            if (showErrorMsg) {
              showError(errorMsg)
            }
            reject(new Error(errorMsg))
          }
        }
      },
      fail: (error) => {
        console.error('上传失败:', error)
        
        let errorMsg = '上传失败'
        if (error.errMsg) {
          errorMsg = error.errMsg
          
          // 特殊错误处理
          if (error.errMsg.includes('ERR_UNSAFE_PORT')) {
            errorMsg = '网络端口不安全，请联系管理员检查配置'
          } else if (error.errMsg.includes('timeout')) {
            errorMsg = '上传超时，请检查网络连接'
          } else if (error.errMsg.includes('fail')) {
            errorMsg = '文件上传失败，请重试'
          }
        }
        
        console.error('最终错误信息:', errorMsg)
        // 检查是否是搜索相关的请求，如果是则静默处理
        const isSearchRequest = config.url && (config.url.includes('/search/') || config.url.includes('search'))
        if (showErrorMsg && !isSearchRequest) {
          uni.showToast({
            title: errorMsg,
            icon: 'none',
            duration: 3000
          })
        } else if (isSearchRequest) {
          console.log('搜索请求错误（静默处理）:', errorMsg)
        }
        reject(new Error(errorMsg))
      },
      complete: () => {
        if (showProgress) {
          uni.hideLoading()
        }
      }
    })
  })
}

// 刷新token的方法
async function refreshAccessToken() {
  const refreshToken = typeof uni !== 'undefined' ? 
    uni.getStorageSync('refreshToken') : 
    (typeof localStorage !== 'undefined' ? localStorage.getItem('refreshToken') : '')
  
  if (!refreshToken) {
    throw new Error('没有可用的刷新令牌')
  }
  
  try {
    const response = await uni.request({
      url: getEnv('VUE_APP_BASE_API', 'http://localhost:6000') + '/user/auth/refresh',
      method: 'POST',
      header: {
        'Content-Type': 'application/json'
      },
      data: {
        refreshToken: refreshToken
      }
    })
    
    if (response.statusCode === 200 && response.data) {
      const { accessToken } = response.data
      
      // 保存新的accessToken
      if (typeof uni !== 'undefined') {
        uni.setStorageSync('accessToken', accessToken)
      } else {
        localStorage.setItem('accessToken', accessToken)
      }
      
      return accessToken
    } else {
      throw new Error('刷新令牌失败')
    }
  } catch (error) {
    console.error('刷新token失败:', error)
    // 刷新失败，清除所有认证信息
    handleUnauthorized()
    throw error
  }
}

// 导出request实例和方法
export default {
  // 通用请求方法
  request,
  
  // 常用HTTP方法
  get: (url, params, config = {}) => {
    return request({
      url,
      method: 'GET',
      params,
      ...config
    })
  },
  
  post: (url, data, config = {}) => {
    return request({
      url,
      method: 'POST',
      data,
      ...config
    })
  },
  
  put: (url, data, config = {}) => {
    return request({
      url,
      method: 'PUT',
      data,
      ...config
    })
  },
  
  delete: (url, config = {}) => {
    return request({
      url,
      method: 'DELETE',
      ...config
    })
  },
  
  patch: (url, data, config = {}) => {
    return request({
      url,
      method: 'PATCH',
      data,
      ...config
    })
  },
  
  // 文件上传
  upload: uploadFile,
  
  // 下载文件
  download: (url, config = {}) => {
    if (typeof uni !== 'undefined') {
      return new Promise((resolve, reject) => {
        uni.downloadFile({
          url: url.startsWith('http') ? url : config.baseURL + url,
          success: resolve,
          fail: reject
        })
      })
    } else {
      // Web端下载
      const link = document.createElement('a')
      link.href = url
      link.download = ''
      if (typeof document !== 'undefined') {
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
      }
      return Promise.resolve()
    }
  }
}

// 立即清除任何可能卡住的加载状态，提升用户体验
if (typeof uni !== 'undefined') {
  try {
    uni.hideLoading()
  } catch (e) {
    // 忽略错误
  }
}